package com.powernode.lambda.simpleStream;


import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.*;

/**
 * 自己实现简单的Stream功能
 */
public class SimpleStream01<T> {

    private Collection<T> collection;
    private SimpleStream01(Collection<T> collection) {
        this.collection =collection;
    }

    /**
     * 根据给出的链式调用手写出需要调用的方法
     * @param args
     */
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

//        SimpleStream01.of(list)
//                .filter(x->(x&1)==1)
//                .map(x->x*x)
//                .forEach(System.out::println);

        System.out.println("求和 = " + SimpleStream01.of(list).reduce(0, (x, y) -> Integer.sum(x, y)));
        System.out.println("求最大值 = " + SimpleStream01.of(list).reduce(Integer.MIN_VALUE, (x, y) -> Integer.max(x, y)));
        System.out.println("求最小值 = " + SimpleStream01.of(list).reduce(Integer.MAX_VALUE, (x, y) -> Integer.min(x, y)));
    }

    /**
     * 遍历集合，把该集合中的第一个参数和第二个参数根据传入规则进行处理，
     * 得到的结果继续和下一个参数根据传入规则进行处理，以此类推
     * 可以求和，求最大值，最小值
     * @param o 初始值，根据情况不同传参不同
     * @param binaryOperator
     * @return
     */
    public T reduce(T o,BinaryOperator<T> binaryOperator){
        T now = o;//上次的合并结果
        for (T t : collection) { //t为本次遍历的元素
            now = binaryOperator.apply(now, t);
        }
        return now;
    }

    public void forEach(Consumer<T> consumer){
        for (T t : collection) {
            consumer.accept(t);
        }
    }

    public <U> SimpleStream01<U> map(Function<T, U> function){
        List<U> objects = new ArrayList<>();
        for (T t : collection) {
            U apply = function.apply(t);
            objects.add(apply);
        }
        return new SimpleStream01<>(objects);
    }

    public SimpleStream01<T> filter(Predicate<T> predicate){
        List<T> objects = new ArrayList<>();
        for (T t : collection) {
            if (predicate.test(t)){
                objects.add(t);
            }
        }
        return new SimpleStream01<>(objects);
    }

    public static <T> SimpleStream01<T> of(Collection<T> collection){
        return new SimpleStream01<>(collection);
    }


}
